#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include "main.h"
#include "wallinit.h"
#include "pkgFlow.h"
#include "firewallHint.h"
#include "firewallConfig.h"

// Windows cmd 专属限定版
#define cls system("cls")

char* cfgname;
char* portcfgname;
char* protocolcfgname;
char* netcardcfgname;
char* tmpname;
time_t TTL;
int totalIPLines;
int totalPtLines;
char* protocol[NUM_PROTOCOL];
char* netcard[NUM_NETCARD];

static inline int goon(void)
{
    char ret;
    do
    {
        printf("\nContinue next turn?\n");
        printf("(y/n) ");
        scanf("%c", &ret);
    } while (ret != 'y' && ret != 'n');

    return ret == 'y';
}

static inline bool illegalMode(char mode)
{
    return !(mode >= '1' && mode <= '7') && mode != 'q';
}

static char selectMode(void)
{
    selectHint();
    char mode;
    do
    {
        scanf("%c", &mode);
    } while (illegalMode(mode));

    return mode;
}

static void dynamicMode(void)
{
    int cnt;
    int amount;
    while (1)
    {
        cnt = 0;
        DMstart:
        amount = getAmount();

        // 用于指向一次模拟产生的 IP 地址
        Package* oriIPsets = (Package*)malloc(amount * sizeof(Package));

        // 用于指向筛选后的 IP 地址
        Package* IPsets = (Package*)malloc(amount * sizeof(Package));

        // 对比数据包是否被禁止通过
        amount = checkBanned(amount, getFlow(amount, oriIPsets), IPsets);
        free(oriIPsets);

        if (amount)
        {
            // 输出获取的数据包信息
            showPkg(amount, IPsets);

            // 要求用户输入，将结果写入文件
            configByFlow(amount, IPsets);

            free(IPsets);
        }
        else
        {
            free(IPsets);
            cnt++;
            if (cnt >= 5)
            {
                printf("All Packages Were Stopped By Wall!\n");
                // 清空缓冲区的回车
                getchar();
            }
            else
                goto DMstart;
        }

        // 选择是否继续
        if (!goon()) break;
        printf("\n");
    }

}

static void staticMode(void)
{
    while (1)
    {
        staticIPConfig();
        if (!goon()) break;
        printf("\n");
    }
}

static void portMode(void)
{
    while (1)
    {
        staticPortConfig();
        if (!goon()) break;
        printf("\n");
    }
}

static void protocolMode(void)
{
    char* cmd = (char*)malloc((MAX_FILE_PATH_LEN + 28) * sizeof(char));

    while (1)
    {
        showCfg(protocolcfgname, cmd);
        protocolConfig();
        if (!goon()) break;
        printf("\n");
    }

    free(cmd);
}

static void netcardMode(void)
{
    char* cmd = (char*)malloc((MAX_FILE_PATH_LEN + 28) * sizeof(char));

    while (1)
    {
        showCfg(netcardcfgname, cmd);
        netcardConfig();
        if (!goon()) break;
        printf("\n");
    }
    
    free(cmd);
}

static void listCfg(void)
{
    char* cmd = (char*)malloc((MAX_FILE_PATH_LEN + 28) * sizeof(char));

    printf("* Configurations of IP\n");
    showCfg(cfgname, cmd);

    printf("* Configurations of Port\n");
    showCfg(portcfgname, cmd);

    printf("* Configurations of Protocol\n");
    showCfg(protocolcfgname, cmd);

    printf("* Configurations of Net Card\n");
    showCfg(netcardcfgname, cmd);

    free(cmd);
}

int main(int argc, char const *argv[])
{
    cfgname = (char*)malloc((MAX_FILE_PATH_LEN + 23) * sizeof(char));
    portcfgname = (char*)malloc((MAX_FILE_PATH_LEN + 21) * sizeof(char));
    protocolcfgname = (char*)malloc((MAX_FILE_PATH_LEN + 23) * sizeof(char));
    netcardcfgname = (char*)malloc((MAX_FILE_PATH_LEN + 21) * sizeof(char));
    tmpname = (char*)malloc((MAX_FILE_PATH_LEN + 22) * sizeof(char));

    for (int i = 0; i < NUM_PROTOCOL; i++)
        protocol[i] = (char*)malloc((MAX_FILE_PATH_LEN + 1) * sizeof(char));
    for (int i = 0; i < NUM_NETCARD; i++)
        netcard[i] = (char*)malloc((MAX_NETCARD_NAME_LEN + 1) * sizeof(char));

    initwall();

    printf("Checking Expired Items...\n");
    refreshCfg(1);
    refreshCfg(0);
    printf("Refresh Config File Succeeded!\n");

    system("pause");
    cls;

    // 函数跳转表
    void (*fp[])(void) = { dynamicMode, staticMode, portMode, protocolMode, netcardMode, listCfg };

    while (1)
    {
        char mode = selectMode();
        cls;
        if (mode == 'q')
            break;
        else if (!illegalMode(mode))
            (*fp[mode - '1'])();
        else
            printf("Incorrect Command!\n");

        system("pause");
        cls;
    }


    free(cfgname);
    free(tmpname);

    return 0;
}